This short tutorial is about a simple LED and timer demo for a CY7C68013A EZ-USB FX2LP USB2.0 Development Board. Such boards are widely available via different channels. The one used here was bought on ebay. The author used a Debian GNU/Linux system, but the tutorial should work for other Linux distributions, *BSD or other Unices.
The tools we use are
The CY7C68013A EZ-USB FX2LP USB2.0 Development Board is connected to the host computer via a USB cable for power and to write the demo onto the board.
Depending on your operating system there might be an easy way to install SDCC 3.5.0 or newer using a package system or similar (e.g. apt-get install sdcc on Debian). While SDCC 3.4.0 should be sufficient for this tutorial, you might want to try a newer version in case you encounter any bugs.
SDCC binaries or a source tarball can be downloaded from its website.
Depending on your operating system there might be an easy way to install cycfx2prog using a package system or similar (e.g. apt-get install sdcc on Debian).
A source tarball can be downloaded from its website.
We present a simple Demo that increments a 2-bit LED counter once per second. This demonstrates setting up and using an accurate timer and doing basic I/O. Here is the C code:
// Source code under CC0 1.0 #include <stdbool.h> __sfr __at(0x80) IOA; __sfr __at(0xb2) OEA; __sfr __at(0x88) TCON; __sfr __at(0x89) TMOD; __sfr __at(0x8a) TL0; __sfr __at(0x8c) TH0; __sfr __at(0xa8) IE; volatile unsigned long int clocktime; volatile _Bool clockupdate; void clockinc(void) __interrupt(1) { TH0 = (65536 - 1000) / 256; TL0 = (65536 - 1000) % 256; clocktime++; clockupdate = true; } unsigned long int clock(void) { unsigned long int ctmp; do { clockupdate = false; ctmp = clocktime; } while (clockupdate); return(ctmp); } void main(void) { // Configure timer // 1000 ticks per second TH0 = (65536 - 1000) / 256; TL0 = (65536 - 1000) % 256; TMOD = 0x01; IE |= 0x82; TCON |= 0x10; // Start timer OEA=0x03; // port A as output for(;;) IOA = ~(clock() / 1000) & 0x03; }
SDCC is a freestanding, not a hosted implemenatation of C, and allows main to return void.
We set up the timer to generate an interupt once per millisecond, which allows us to implement a basic clock()
function. This function is used to control the blinking of the LEDs.
The demo can be compiled simply by invocing sdcc using sdcc -mmcs51 --std-c99 led.c
assuming the C code is in led.c. The option -mmcs51
selects the target port (mcs51). An .ihx file with a name corresponding to the source file will be generated.
Assuming the board is attached via USB, cycfx2prog prg:led.ihx run
will write the demo onto the board. It will run and count up to 3 on the red LEDs, then start again at 0.
cycfx2prog was written by Wolfgang Wieser. It is a tool to program the FX2 (i.e. to download '8051 firmware into the RAM) and do basic endpoint communication for testing purposes. cycfx2prog requires the input file to be an .ihx Intel hex file.
SDCC was initially written by Sandeep Dutta for the MCS-51, and has a relatively conservative architecture (see Sandeep Dutta, "Anatomy of a Compiler", 2000). It has been extended by various contributors and more recently, incorporated some cutting-edge technologies, in particular in register allocation (see Philipp Klaus Krause, "Optimal Register Allocation in Polynomial Time", 2013 and "Bytewise Register Allocation", 2015). However the mcs51 backend does not have all the fancy features and optimizations that some newer backends have.
SDCC is a C compiler that aims to be compliant with the C standards.
Important compiler options for MCS-51 developers include:
-c
to compile into object files to be linked later--std-c99
for compilation in C99 mode (some C99 features, e.g. variable-length arrays are not yet supported in sdcc though)--model-large
to use the xram for variables by default